﻿/****************************************
* File description: deugLog.h
* Function: 日志打印模块
* CurrentVersion: 1.0.0
* Author: JNN
* Date: 2025-07-01
*  -----
* Copyright by 博坤生物
*****************************************/

#ifndef DEBUGLOG_H
#define DEBUGLOG_H

#include <QDir>

#include <QTime>
#include <QDebug>

#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDatabase>
#include <QThread>

#define DEBUG_SOFTWARE_NAME "96-RT-PCR"

// 打印级别
#define DEBUG_MODE 2        // 0 不打印
                            // 1 用户环境
                            // 2 测试环境

#include "logThread.h"

// ============================== 调用接口Start ======================================

// 通用打印 (a可传入任意类型参数，输出格式和qDebug()打印的格式相同)
#define __LOG_DEBUG(text)  DebugLog::I().debug(DEBUG_CONTEXT, text)
#define __LOG_WARN(text)   DebugLog::I().warning(DEBUG_CONTEXT, text)
#define __LOG_ERROR(text)  DebugLog::I().error(DEBUG_CONTEXT, text)
#define __LOG_INFO(text)   DebugLog::I().info(DEBUG_CONTEXT, text)

// 函数开始和结束时调用 (带参数)
#define __LOG_FSTART(text) DebugLog::I().funcStart(DEBUG_CONTEXT, text)
#define __LOG_FEND(text)   DebugLog::I().funcEnd(DEBUG_CONTEXT, text)
// 函数开始和结束时调用 (不带参数)
#define __LOG_FSTART__  DebugLog::I().funcStart(DEBUG_CONTEXT)
#define __LOG_FEND__    DebugLog::I().funcEnd(DEBUG_CONTEXT)

// 循环开始和结束时调用
#define __LOG_CSTART(text) DebugLog::I().cycleStart(DEBUG_CONTEXT, text)
#define __LOG_CEND(text)   DebugLog::I().cycleEnd(DEBUG_CONTEXT, text)

// 自定义类型打印 （打印出来的文件名为 Log_软件名_日期_type.txt）
#define __LOG0(text, type)  DebugLog::I().customType(text, type)                    // 不打印额外信息
#define __LOG1(text, type)  DebugLog::I().customType(DEBUG_CONTEXT, text, type)     // 打印当前位置（cpp文件、函数名）

// 为什么要用txt做后缀，因为log后缀的文件在安卓屏上打不开，我还得导出来才能看…………

// ============================== 调用接口End =======================================


// 打印当前函数信息
//#define DEBUG_CONTEXT   QString(__FILE__).split("/").back() + " Line" + QString("%1").arg(__LINE__, 3, 10, QLatin1Char('0')) + " " + QString(__func__) +  "()"
#define DEBUG_CONTEXT     QString(__FILE__).split("/").back().remove(".cpp") + "  " + QString(__func__) + "()"

#ifdef Q_OS_ANDROID
#define DEBUG_ONSCREEN true
#else
#define DEBUG_ONSCREEN false
#endif


class DebugLog
{

private:
    DebugLog();

public:
    static DebugLog& I();

    void write(QString text, QString type = "");

    // ========================= 函数开始和结束 ================================
    void funcStart(QString context){
        if(DEBUG_MODE == 0) return;
        write("[FSTA]  " + context);
    }
    void funcEnd(QString context){
        if(DEBUG_MODE == 0) return;
        write("[FEND]  " + context);
    }

    template<typename T>
    void funcStart(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[FSTA]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void funcEnd(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[FEND]  " + context + "  " + qobj2qstr(text));
    }

    // =========================== 循环开始和结束 ===============================
    template<typename T>
    void cycleStart(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[CSTA]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void cycleEnd(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[CEND]  " + context + "  " + qobj2qstr(text));
    }


    // ========================== 其它通用类型 ===============================
    template<typename T>
    void debug(QString context, T text){
        if(DEBUG_MODE < 2) return;
        write("[DEBU]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void info(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[INFO]  " + context + "  " + qobj2qstr(text));
    }

    template<typename T>
    void warning(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[WARN]  " + context + "  " + qobj2qstr(text));
    }

    template<typename T>
    void error(QString context, T text){
        qDebug() << "-------------------------------------------------------------------------";
        qDebug() << "[ERROR]" << context << text;
        qDebug() << "-------------------------------------------------------------------------";
        if(DEBUG_MODE == 0) return;
        write("[ERRO]  " + context + "  " + qobj2qstr(text), "ERROR");
    }

    // ============================= 其它日志类型 ==================================
    void sql(QString sql, QString res, QString info){      // 数据库日志
        if(DEBUG_MODE < 2) return;
        write(res + "  " + sql + "  [RES]" + info, "SQL");
    }
    void communication(QString text, int type){      // 0 发送 1 接收
        write((type==0?"[SEND]":"[RECV]  ") + text, "Comm");
    }


    template<typename T>
    void customType(T text, QString type){
        write(qobj2qstr(text), type);
    }
    template<typename T>
    void customType(QString context, T text, QString type){
        write(context + "  " + qobj2qstr(text), type);
    }



    // 将不知道什么类型的东西转成字符串类型
    template<typename T>
    QString qobj2qstr(T obj){
        QString str;
        QDebug debug(&str);
        debug << obj;
        return str;
    }

    QString    _outRootDir;
    LogThread*   _thread;

};

// QSqlQurery重载，用于打印执行的SQL语句
class QSqlQueryDebug : public QSqlQuery{

    // 数据库返回结果行数
    int sqlSize(QSqlQuery* query){
        int initialPos = query->at();
        int pos = 0;
        if (query->last())  pos = query->at() + 1;
        query->seek(initialPos);
        return pos;
    }
public:

    QSqlQueryDebug(QSqlDatabase db) : QSqlQuery(db){
    }
    QSqlQueryDebug(const QString& query = QString(), QSqlDatabase db = QSqlDatabase()) : QSqlQuery(query, db){
    }
    QSqlQueryDebug(QSqlResult *r) : QSqlQuery(r){
    }

    bool exec(){
        return QSqlQuery::exec();
    }
    bool exec(const QString& query){
        bool res = QSqlQuery::exec(query);
        if(res){
            DebugLog::I().sql(query, "[SUCC]", QString::number(sqlSize(this)));
        }else{
            DebugLog::I().sql(query, "[FAIL] ", this->lastError().text());
        }
        return res;
    }

};

#define QSqlQuery QSqlQueryDebug

#endif // DEBUGLOG_H
